import { Injectable, OnModuleDestroy, OnApplicationShutdown, Logger } from '@nestjs/common';
import { SchedulerRegistry, Cron } from '@nestjs/schedule';
import { CronJob, CronJobParams, CronTime } from 'cron'
import { TASK_CRON_MAP } from '@/enums/task'
import { IndicatorService } from '@/modules/data/indicator/indicator.service'

@Injectable()
export class TasksService implements OnModuleDestroy, OnApplicationShutdown {
  constructor(
    private schedulerRegistry: SchedulerRegistry,
    private indicatorService: IndicatorService
  ) { }

  private readonly logger = new Logger(TasksService.name);

  @Cron(TASK_CRON_MAP[1], { name: 'indicator' })
  triggerIndicator() {
    this.indicatorService.indicatorTask()
  }

  // 模块启用时调用
  // async onApplicationBootstrap(){
  //   console.log('onApplicationBootstrap')
  //  await this.startAllTask()
  // }

  // 模块销毁时调用
  async onModuleDestroy() {
    this.logger.log('Module destroy hook called');
    await this.stopAllTask();
  }

  // 应用程序关闭时调用
  async onApplicationShutdown(signal?: string) {
    this.logger.log(`Application shutdown hook called with signal: ${signal}`);
    await this.stopAllTask();
  }

  /**
   * 添加task
   * @param name 名称
   * @param cronTime CronJobParams['cronTime']
   * @param taskFun 回调
   */
  addTask(name: string, cronTime: CronJobParams['cronTime'], taskFun: Function) {
    const taskJob = this.getTask(name);
    if (taskJob) return

    const job = new CronJob(cronTime, async () => {
      try {
        await taskFun();
      } catch (error) {
        this.logger.error(`job [${name}] error: ${error}`);
      }
    });
    this.schedulerRegistry.addCronJob(name, job);
    job.start();
    this.logger.warn(`time (${cronTime}) for job [${name}] to run!`);
  }

  /**
   * 获取task
   * @param name 名称
   * @returns CronJob
   */
  getTask(name: string) {
    try {
      const job = this.schedulerRegistry.getCronJob(name);
      return job;
    } catch {
      return null
    }
  }

  /**
   * 获取所有task
   * @returns CronJob[]
   */
  getAllTask() {
    const jobs = this.schedulerRegistry.getCronJobs();
    return jobs;
  }

  /**
   * 删除task
   * @param name 名称
   */
  deleteTask(name: string) {
    const job = this.getTask(name);
    job && this.schedulerRegistry.deleteCronJob(name);
    this.logger.warn(`job [${name}] deleted!`);
  }

  /**
   * 删除所有task
   */
  deleteAllTasks() {
    const jobs = this.getAllTask();
    jobs.forEach((_, name) => {
      this.deleteTask(name);
    })
    this.logger.warn(`all job delete!`);
  }

  /**
   * 启动task
   * @param name 名称
   */
  startTask(name: string) {
    const job = this.getTask(name);
    job && job.start();
    this.logger.warn(`job [${name}] start!`);
  }

  /**
   * 启用所有task
   */
  startAllTask() {
    const jobs = this.getAllTask();
    jobs.forEach(job => job.start())
    this.logger.warn(`all job start!`);
  }

  /**
   * 停止task
   * @param name 名称
   */
  stopTask(name: string) {
    const job = this.getTask(name);
    job && job.stop();
    this.logger.warn(`job [${name}] stop!`);
  }

  /**
   * 停止所有task
   */
  stopAllTask() {
    const jobs = this.getAllTask();
    jobs.forEach(job => job.stop())
    this.logger.warn(`all job stop!`);
  }

  /**
   * 停止作业，为其设置新时间，然后启动它
   */
  setTime(name: string, time: CronTime) {
    const job = this.getTask(name);
    job && job.setTime(time);
  }
}